home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / PAINT.PAK / PAINT.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  35KB  |  1,362 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1991, 1995 by Borland International, All Rights Reserved
  4. //
  5. // $Revision:   10.13  $
  6. //
  7. // Example paint program
  8. //----------------------------------------------------------------------------
  9. #include <owl/pch.h>
  10. #include <owl/applicat.h>
  11. #include <owl/dc.h>
  12. #include <owl/dibitmap.h>
  13. #include <owl/gdiobjec.h>
  14. #include <owl/decframe.h>
  15. #include <owl/chooseco.h>
  16. #include <owl/choosefo.h>
  17. #include <owl/opensave.h>
  18. #include <owl/printdia.h>
  19. #include <owl/scroller.h>
  20. #include <owl/controlb.h>
  21. #include <owl/floatfra.h>
  22. #include <owl/toolbox.h>
  23. #include <owl/buttonga.h>
  24. #include <owl/editfile.rh>
  25. #include <stdio.h>
  26. #include <dir.h>
  27. #include "paint.rh"
  28. #include "dibattr.h"
  29.  
  30. DIAG_DEFINE_GROUP(PaintDrw,1,0);  // drawing tracing (set level to 1 for mouse)
  31. DIAG_DEFINE_GROUP(PaintCmd,1,0);  // command tracing
  32.  
  33. //
  34. // Build options
  35. //
  36. //#define USE_LINEBAR     // Comment out for line gadgets instead of line bar
  37. //#define USE_TOOLBAR     // Uncomment out to have non-floating toolbar
  38. #define PARALLEL_PEN      // To enable parallel line drawing with pen tool
  39.  
  40. const int    DefWidth  = 640;
  41. const int    DefHeight = 480;
  42.       uint32 DefNColors= 0;        // fill in with screen device info
  43. const int    DefPenSize= 3;
  44.  
  45. const TColor DefPalette[] = {
  46.   0x000000L, 0xFFFFFFL, 0x7F7F7FL, 0xC0C0C0L,
  47.   0x00007FL, 0x007F00L, 0x007F7FL, 0x7F0000L, 
  48.   0x7F007FL, 0x7F7F00L, 0x0000FFL, 0x00FF00L, 
  49.   0x00FFFFL, 0xFF0000L, 0xFF00FFL, 0xFFFF00L,
  50. };
  51.  
  52. const int CM_TOOL   = 300;
  53. const int CM_LINE   = 400;
  54. const int ToolCount = 6;
  55.  
  56. const int ID_CANVAS = 101;
  57. const int ID_PALETTE= 102;
  58.  
  59. #if defined(USE_LINEBAR)
  60. const int LineCount = 8;
  61. const int LineBarWidth = LineCount * 4 + 6 + (1 + 2 + 3 + 4 + 5 + 7 + 9 + 12);
  62. const int LineWidth[LineCount] = { 1, 2, 3, 4, 5, 7, 9, 12 };
  63. #endif
  64.  
  65.  
  66. //----------------------------------------------------------------------------
  67.  
  68. class TDrawTool;
  69.  
  70. //
  71. //
  72. //
  73. struct TState {
  74.     TDrawTool*  DrawTool;
  75.     TDC*        DC;
  76.     TPalette*   Palette;
  77.     TDib*       Dib;
  78.     TBitmap*    Bitmap;
  79.     int         PenSize;
  80.     int         FgColor;
  81.     int         BgColor;
  82.     string      Name;
  83.     string      Title;
  84.     bool        Modified;
  85. };
  86.  
  87. //
  88. //
  89. //
  90. class TDrawTool {
  91.   public:
  92.     TDrawTool(const char* name);
  93.  
  94.     void      MouseDown(TWindow& window, const TPoint& point, TState* state);
  95.     void      MouseMove(const TPoint& Point);
  96.     void      MouseUp();
  97.  
  98.     const char*  GetName() {return Name;}
  99.  
  100.   protected:
  101.     virtual void DrawBegin(const TPoint& point) {}
  102.     virtual void DrawTo(const TPoint& point) {}
  103.     virtual void DrawEnd() {}
  104.     virtual bool UsesPenOnly() {return false;}
  105.  
  106.     TCursor*     Cursor;
  107.     TIcon*       Icon;
  108.     TState*      State;
  109.     TWindow*     Window;
  110.     TPen*        Pen;
  111.     TBrush*      Brush;
  112.     TDC*         DC;
  113.     TPoint       LastPoint;
  114.     TRect        Bounds;
  115.  
  116.   private:
  117.     const char*  Name;
  118. };
  119.  
  120. //
  121. //
  122. //
  123. class TPenTool : public TDrawTool {
  124.   public:
  125.     TPenTool(const char* name) : TDrawTool(name) {}
  126.  
  127.   protected:
  128.     virtual void DrawBegin(const TPoint& point);
  129.     virtual void DrawTo(const TPoint& point);
  130.     virtual void DrawEnd();
  131.     virtual bool UsesPenOnly() {return true;}
  132.  
  133. #if defined(PARALLEL_PEN)
  134.     TPalette*       TmpPalette;
  135. #endif
  136. };
  137.  
  138. //
  139. //
  140. //
  141. class TFillTool : public TDrawTool {
  142.   public:
  143.     TFillTool(const char* name) : TDrawTool(name) {}
  144.   protected:
  145.     virtual void    DrawBegin(const TPoint& point);
  146. };
  147.  
  148. class TBoxTool : public TDrawTool {
  149.   public:
  150.     TBoxTool(const char* name, bool filled)
  151.              : TDrawTool(name), Filled(filled) {}
  152.  
  153.   protected:
  154.     virtual void    DrawBegin(const TPoint& point);
  155.     virtual void    DrawTo(const TPoint& point);
  156.     virtual void    DrawEnd();
  157.     virtual void    DrawObject(TDC& dc) {}
  158.  
  159.   protected:
  160.     bool        Filled;
  161.     int         X1;
  162.     int         Y1;
  163.     int         X2;
  164.     int         Y2;
  165. };
  166.  
  167. class TRectTool : public TBoxTool {
  168.   public:
  169.     TRectTool(const char* name, bool filled) : TBoxTool(name, filled) {}
  170.   protected:
  171.     virtual void DrawObject(TDC& dc);
  172. };
  173.  
  174. class TEllipseTool : public TBoxTool {
  175.   public:
  176.     TEllipseTool(const char* name, bool filled) : TBoxTool(name, filled) {}
  177.   protected:
  178.     virtual void DrawObject(TDC& dc);
  179. };
  180.  
  181. //----------------------------------------------------------------------------
  182.  
  183. class TPaletteWindow : public TWindow {
  184.   public:
  185.     TPaletteWindow(TWindow* parent, TState* state);
  186.     void         SelectColor(TPoint& point, int& color);
  187.  
  188.   protected:
  189.     void         Paint(TDC&, bool, TRect&);
  190.  
  191.     void         EvSize(UINT, TSize&);
  192.     void         EvLButtonDown(UINT modKeys, TPoint& point);
  193.     void         EvLButtonDblClk(UINT modKeys, TPoint&);
  194.     void         EvRButtonDown(UINT modKeys, TPoint& point);
  195.     void         EvRButtonDblClk(UINT modKeys, TPoint& point);
  196.     LRESULT      EvSetRGB(TParam1, TParam2);
  197.  
  198.   private:
  199.     TState*      State;
  200.     bool         Horz;
  201.     int          Cx;      // Count of panes in the X direction
  202.     int          Cy;      // Count of panes in the Y direction
  203.     int          Dx;      // Size of a pane in the X direction
  204.     int          Dy;      // Size of a pane in the Y direction
  205.  
  206.   DECLARE_RESPONSE_TABLE(TPaletteWindow);
  207. };
  208.  
  209. DEFINE_RESPONSE_TABLE1(TPaletteWindow, TWindow)
  210.   EV_WM_SIZE,
  211.   EV_WM_LBUTTONDOWN,
  212.   EV_WM_LBUTTONDBLCLK,
  213.   EV_WM_RBUTTONDOWN,
  214.   EV_WM_RBUTTONDBLCLK,
  215.   EV_REGISTERED(SETRGBSTRING, EvSetRGB),
  216. END_RESPONSE_TABLE;
  217.  
  218. //----------------------------------------------------------------------------
  219.  
  220. //
  221. // A slightly customized floating frame for use as our tool & style button
  222. // palettes.
  223. //
  224. class TButtonPalette : public TFloatingFrame {
  225.   public:
  226.     TButtonPalette(TWindow*        parent,
  227.                    char*           title = 0,
  228.                    TWindow*        clientWnd = 0,
  229.                    TModule*        module = 0);
  230.  
  231.   private:
  232.     void SetupWindow();
  233.     void CleanupWindow();
  234.     void EvClose();
  235.  
  236.   DECLARE_RESPONSE_TABLE(TButtonPalette);
  237. };
  238.  
  239. DEFINE_RESPONSE_TABLE1(TButtonPalette, TFloatingFrame)
  240.   EV_WM_CLOSE,
  241. END_RESPONSE_TABLE;
  242.  
  243. TButtonPalette::TButtonPalette(TWindow* parent, char* title,
  244.                                TWindow* clientWnd, TModule* module)
  245. :
  246.   TFloatingFrame(parent, title, clientWnd, true, DefaultCaptionHeight, true,
  247.                  module)
  248. {
  249. }
  250.  
  251. //
  252. // Supply a reasonable startup position relative to our Parent (owner actually)
  253. //
  254. void
  255. TButtonPalette::SetupWindow()
  256. {
  257.   TFloatingFrame::SetupWindow();
  258.  
  259.   if (Attr.X < 0 || Attr.Y < 0) {
  260.     TRect parentRect;
  261.     GetParentO()->GetWindowRect(parentRect);
  262.     SetWindowPos(0, parentRect.left+10, parentRect.top+10, 0, 0,
  263.                  SWP_NOSIZE | SWP_NOZORDER);
  264.   }
  265. }
  266.  
  267. //
  268. // Remember latest position when we are destroyed, so we can reappear in the
  269. // same place when re-enabled.
  270. //
  271. void
  272. TButtonPalette::CleanupWindow()
  273. {
  274.   TRect rect;
  275.   GetWindowRect(rect);
  276.   Attr.X = rect.left;
  277.   Attr.Y = rect.top;
  278.  
  279.   TFloatingFrame::CleanupWindow();
  280. }
  281.  
  282. //
  283. // Override EvClose to keep TWindow from having us deleted. We want to keep the
  284. // OWL object around even when the window is destroyed.
  285. //
  286. void
  287. TButtonPalette::EvClose()
  288. {
  289.   CloseWindow();
  290. }
  291.  
  292. //----------------------------------------------------------------------------
  293.  
  294. #if defined(USE_LINEBAR)
  295. class TLineBar : public TWindow {
  296.   public:
  297.     TLineBar(TWindow* parent, TState* state);
  298.  
  299.     void         Paint(TDC&, bool, TRect&);
  300.     void         EvLButtonDown(UINT modKeys, TPoint& point);
  301.  
  302.   private:
  303.     TState*     State;
  304.     void        Notch(TDC& dc, int x, int w, int y, int dy);
  305.  
  306.   DECLARE_RESPONSE_TABLE(TLineBar);
  307. };
  308.  
  309. DEFINE_RESPONSE_TABLE1(TLineBar, TWindow)
  310.   EV_WM_LBUTTONDOWN,
  311. END_RESPONSE_TABLE;
  312. #endif
  313.  
  314. //----------------------------------------------------------------------------
  315.  
  316. // 
  317. // Given the bits-per-pixel depth of a DIB or a display device, return
  318. // the maximum number of colors that DIB or device could use.
  319. //
  320. uint32 ColorCapacity(uint depth)
  321. {
  322.   switch (depth) {
  323.     case 1:  return 2;
  324.     case 2:  return 4;
  325.     case 4:  return 16;
  326.     case 8:  return 256;
  327.     case 16: return 65536L;
  328.     default: return 16777216L;
  329.   }
  330. }
  331.  
  332. //----------------------------------------------------------------------------
  333.  
  334. class TCanvas : public TWindow {
  335.   public:
  336.     TCanvas();
  337.    ~TCanvas();
  338.  
  339.     TState       State;
  340.  
  341.   protected:
  342.     // Override TWindow virtuals
  343.     //
  344.     void         SetupWindow();
  345.     bool         CanClose();
  346.  
  347.     bool         AbandonOk();
  348.     void         SetupDib(TDib* dib, const char* fileName, const char* fileTitle);
  349.     void         NewDib(int width, int height, uint32 nColors);
  350.     void         OpenDib(const char* fileName, const char* fileTitle);
  351.     bool         SaveDib(const char* fileName);
  352.  
  353.     void         UpdateCaption();
  354.     void         AdjustScroller();
  355.     void         Paint(TDC&, bool, TRect&);
  356.  
  357.     void         EvSize(UINT, TSize&);
  358.     void         EvLButtonDown(UINT modKeys, TPoint& point);
  359.     void         EvLButtonUp(UINT modKeys, TPoint& point);
  360.     void         EvMouseMove(UINT modKeys, TPoint& point);
  361.     void         EvDropFiles(TDropInfo dropInfo);
  362.  
  363.     void         CmFileNew();
  364.     void         CmFileOpen();
  365.     void         CmFileSave();
  366.     void         CmFileSaveAs();
  367.     void         CmFilePrint();
  368.     void         CmFilePrintSetup();
  369.  
  370.     void         CmViewTools();
  371.     void         CeViewTools(TCommandEnabler& ce);
  372.     void         CmViewLines();
  373.     void         CeViewLines(TCommandEnabler& ce);
  374.  
  375.     void         CmTool(TParam1);
  376.     void         CmLine(TParam1);
  377.  
  378.     TPrintDialog::TData PrintData;
  379.  
  380.   private:
  381.     bool         Drawing;
  382.     TDrawTool*   Tools[ToolCount];
  383.  
  384.     TButtonPalette* ToolsPal;
  385.     TButtonPalette* LinesPal;
  386.  
  387.   DECLARE_RESPONSE_TABLE(TCanvas);
  388. };
  389.  
  390. DEFINE_RESPONSE_TABLE1(TCanvas, TWindow)
  391.   EV_WM_SIZE,
  392.   EV_WM_LBUTTONDOWN,
  393.   EV_WM_LBUTTONUP,
  394.   EV_WM_MOUSEMOVE,
  395.   EV_WM_DROPFILES,
  396.   EV_COMMAND_AND_ID(CM_TOOL+0, CmTool),
  397.   EV_COMMAND_AND_ID(CM_TOOL+1, CmTool),
  398.   EV_COMMAND_AND_ID(CM_TOOL+2, CmTool),
  399.   EV_COMMAND_AND_ID(CM_TOOL+3, CmTool),
  400.   EV_COMMAND_AND_ID(CM_TOOL+4, CmTool),
  401.   EV_COMMAND_AND_ID(CM_TOOL+5, CmTool),
  402.   EV_COMMAND_AND_ID(CM_LINE+1, CmLine),
  403.   EV_COMMAND_AND_ID(CM_LINE+3, CmLine),
  404.   EV_COMMAND_AND_ID(CM_LINE+5, CmLine),
  405.   EV_COMMAND_AND_ID(CM_LINE+7, CmLine),
  406.   EV_COMMAND_AND_ID(CM_LINE+9, CmLine),
  407.   EV_COMMAND_AND_ID(CM_LINE+11, CmLine),
  408.   EV_COMMAND(CM_FILENEW, CmFileNew),
  409.   EV_COMMAND(CM_FILEOPEN, CmFileOpen),
  410.   EV_COMMAND(CM_FILESAVE, CmFileSave),
  411.   EV_COMMAND(CM_FILESAVEAS, CmFileSaveAs),
  412.   EV_COMMAND(CM_FILEPRINT, CmFilePrint),
  413.   EV_COMMAND(CM_FILEPRINTERSETUP, CmFilePrintSetup),
  414.   EV_COMMAND(CM_VIEWTOOLS, CmViewTools),
  415.   EV_COMMAND_ENABLE(CM_VIEWTOOLS, CeViewTools),
  416.   EV_COMMAND(CM_VIEWLINES, CmViewLines),
  417.   EV_COMMAND_ENABLE(CM_VIEWLINES, CeViewLines),
  418. END_RESPONSE_TABLE;
  419.  
  420. // --------------- TDrawTool ------------------------
  421.  
  422. TDrawTool::TDrawTool(const char* name)
  423. :
  424.   State(0), Window(0), Pen(0), Brush(0), DC(0), Name(name)
  425. {
  426. }
  427.  
  428. void
  429. TDrawTool::MouseDown(TWindow& window, const TPoint& point, TState* state)
  430. {
  431.   TRACEX(PaintDrw,0,"Draw " << GetName() <<
  432.     " started at (" << point.x << "," << point.y << ")");
  433.   Window = &window;
  434.   State = state;
  435.   Window->SetCapture();
  436.  
  437.   DC = new TClientDC(window);
  438.  
  439.   //
  440.   if (UsesPenOnly()) {
  441.     Pen = new TPen(TColor(State->FgColor), State->PenSize);
  442.   }
  443.   else {
  444.     Brush = new TBrush(TColor(State->FgColor));
  445.     Pen = new TPen(TColor(State->BgColor), State->PenSize);
  446.   }
  447.  
  448.   State->DC->SelectObject(*State->Palette);
  449.   State->DC->RealizePalette();
  450.   State->DC->SelectObject(*Pen);
  451.   if (Brush)
  452.     State->DC->SelectObject(*Brush);
  453.  
  454.   LastPoint = point;
  455.   Bounds = TRect(point, point);
  456.   DrawBegin(point);
  457. }
  458.  
  459. void
  460. TDrawTool::MouseMove(const TPoint& point)
  461. {
  462.   TRACEX(PaintDrw,1,"Draw " << GetName() <<
  463.     " extends to (" << point.x << "," << point.y << ")");
  464.   Bounds |= TRect(point.x, point.y, point.x, point.y);
  465.   DrawTo(point);
  466.   LastPoint = point;
  467. }
  468.  
  469. void
  470. TDrawTool::MouseUp()
  471. {
  472.   TRACEX(PaintDrw,1,"Draw " << GetName() << " finished");
  473.   DrawEnd();
  474.  
  475.   Window->ReleaseCapture();
  476.   State->DC->RestoreObjects();
  477.  
  478.   delete Brush; Brush = 0;
  479.   delete Pen; Pen = 0;
  480.   delete DC; DC = 0;
  481.  
  482.   State->Modified = true;
  483.   Window->InvalidateRect(Bounds.
  484.               InflatedBy((State->PenSize+1)/2,(State->PenSize+1)/2), false);
  485.   Window->UpdateWindow();
  486. }
  487.  
  488. // --------------- TPenTool ------------------------
  489.  
  490. void
  491. TPenTool::DrawBegin(const TPoint& point)
  492. {
  493.   State->DC->MoveTo(point);
  494.  
  495.   // Do parallel update onto screen
  496.   //
  497. #if defined(PARALLEL_PEN)
  498.   // can't select a palette into to different device DCs
  499.   TmpPalette = new TPalette(*State->Palette);
  500.   DC->IntersectClipRect(TRect(TPoint(0,0), State->Dib->Size()));
  501.   DC->SelectObject(*TmpPalette);
  502.   DC->RealizePalette();
  503.  
  504.   DC->SelectObject(*Pen);
  505.   DC->MoveTo(point);
  506. #endif
  507. }
  508.  
  509. void
  510. TPenTool::DrawTo(const TPoint& point)
  511. {
  512.   State->DC->LineTo(point);
  513. #if defined(PARALLEL_PEN)
  514.   DC->LineTo(point);
  515. #else
  516.   Window->InvalidateRect(TRect(LastPoint, point).Normalized().
  517.                  InflatedBy((State->PenSize+1)/2,(State->PenSize+1)/2),false);
  518.   Window->UpdateWindow();
  519. #endif
  520. }
  521.  
  522. void
  523. TPenTool::DrawEnd()
  524. {
  525.   State->DC->RestorePen();
  526. #if defined(PARALLEL_PEN)
  527.   DC->RestorePen();
  528.   delete TmpPalette; TmpPalette = 0;
  529. #endif
  530. }
  531.  
  532. // --------------- TFillTool ------------------------
  533.  
  534. void
  535. TFillTool::DrawBegin(const TPoint& point)
  536. {
  537.   TBrush fgBrush(State->FgColor);
  538.   State->DC->SelectObject(fgBrush);
  539.   TColor surfaceColor(State->DC->GetPixel(point));
  540.   State->DC->ExtFloodFill(point, surfaceColor, FLOODFILLSURFACE);
  541.   Bounds = Window->GetClientRect();
  542.   State->DC->RestoreBrush();
  543. }
  544.  
  545. // --------------- TBoxTool ------------------------
  546.  
  547. void
  548. TBoxTool::DrawBegin(const TPoint& point)
  549. {
  550.   X1 = X2 = point.x;
  551.   Y1 = Y2 = point.y;
  552.   DC->SelectStockObject(BLACK_PEN);
  553.   DC->SelectStockObject(NULL_BRUSH);
  554.   DC->SetROP2(R2_NOT);
  555.   DrawObject(*DC);
  556. }
  557.  
  558. void
  559. TBoxTool::DrawTo(const TPoint& point)
  560. {
  561.   DrawObject(*DC);
  562.   X2 = point.x;
  563.   Y2 = point.y;
  564.   DrawObject(*DC);
  565. }
  566.  
  567. void
  568. TBoxTool::DrawEnd()
  569. {
  570.   DrawObject(*DC);
  571.   DC->SetROP2(R2_COPYPEN);
  572.   State->DC->SelectObject(*Pen);
  573.   if (Filled)
  574.     State->DC->SelectObject(*Brush);
  575.   else
  576.     State->DC->SelectStockObject(NULL_BRUSH);
  577.   DrawObject(*State->DC);
  578. }
  579.  
  580. // --------------- TRectTool ------------------------
  581.  
  582. void
  583. TRectTool::DrawObject(TDC& dc)
  584. {
  585.   dc.Rectangle(X1, Y1, X2, Y2);
  586. }
  587.  
  588. // --------------- TEllipseTool ------------------------
  589.  
  590. void
  591. TEllipseTool::DrawObject(TDC& dc)
  592. {
  593.   dc.Ellipse(X1, Y1, X2, Y2);
  594. }
  595.  
  596. // --------------- TPaletteWindow ------------------------
  597.  
  598. TPaletteWindow::TPaletteWindow(TWindow* parent, TState* state)
  599.   : TWindow(parent),
  600.     State(state)
  601. {
  602.   Attr.Style |= WS_BORDER;
  603.   Attr.W = 50;
  604.   Attr.H = 50;
  605.   Attr.Id = ID_PALETTE;
  606. }
  607.  
  608. void
  609. TPaletteWindow::EvSize(UINT, TSize&)
  610. {
  611.   TRect rect = GetClientRect();
  612.   Horz = true;  // Location==Top || Location==Bottom;
  613.   Cx = (Horz ? 17 : 3);
  614.   Cy = (Horz ? 3 : 17);
  615.   Dx = rect.right / Cx;
  616.   Dy = rect.bottom / Cy;
  617.   if (Horz)
  618.     Cx--;
  619.   else
  620.     Cy--;
  621.   Invalidate(false);
  622. }
  623.  
  624. void
  625. TPaletteWindow::Paint(TDC& dc, bool, TRect&)
  626. {
  627.   dc.SelectObject(*State->Palette);
  628.   dc.RealizePalette();
  629.  
  630.   TRect rect = GetClientRect();
  631.  
  632.   dc.SelectStockObject(BLACK_PEN);
  633.  
  634.   // Paint color selection cells, each with a black frame
  635.   //
  636.   for (int i = 0; i < 16; i++)
  637.     for (int j = 0; j < 3; j++) {
  638.       TBrush brush(TColor(j*16+i));
  639.       dc.SelectObject(brush);
  640.       TPoint p = Horz ? TPoint(i*Dx, j*Dy) : TPoint(j*Dx, i*Dy);
  641.       dc.Rectangle(p, TSize(Dx+1, Dy+1));
  642.       dc.RestoreBrush();
  643.     }
  644.  
  645.   // Paint fore & back color display, frame first
  646.   //
  647.   dc.SelectStockObject(NULL_BRUSH);
  648.   TPoint p = Horz ? TPoint(Dx*16, 0) : TPoint(0, Dy*16);
  649.   dc.Rectangle(p, rect.BottomRight());
  650.  
  651.   TPen pen(TColor(State->BgColor), 5);
  652.   dc.SelectObject(pen);
  653.   TBrush brush(TColor(State->FgColor));
  654.   dc.SelectObject(brush);
  655.   p += TSize(3,3);
  656.   dc.Rectangle(p, TPoint(rect.right-3, rect.bottom-3));
  657. }
  658.  
  659. void
  660. TPaletteWindow::SelectColor(TPoint& point, int& color)
  661. {
  662.   point.x /= Dx;
  663.   point.y /= Dy;
  664.   if (point.x < Cx && point.y < Cy) {
  665.     int newColor = Horz ? point.x + point.y*Cx : point.x*Cy + point.y;
  666.     if (color != newColor) {
  667.       TColor c = State->Dib->GetColor(newColor);
  668.  
  669.       InvalidateRect(Horz ? TRect(TPoint(Dx*Cx, 0), GetClientRect().BottomRight()) :
  670.                             TRect(TPoint(0, Dy*Cy), GetClientRect().BottomRight()),
  671.                      false);
  672.       color = newColor;
  673.     }
  674.   }
  675. }
  676.  
  677. void
  678. TPaletteWindow::EvLButtonDown(UINT, TPoint& point)
  679. {
  680.   SelectColor(point, State->FgColor);
  681. }
  682.  
  683. void
  684. TPaletteWindow::EvLButtonDblClk(UINT, TPoint& point)
  685. {
  686.   static TColor CustColors[32];
  687.  
  688.   int editColor = -1;
  689.   SelectColor(point, editColor);
  690.   if (editColor < 0)
  691.     return;
  692.  
  693.   // If the DIB lacks an adjustable palette, then stop.
  694.   //
  695.   if (State->Dib->NumColors() == 0) 
  696.   {
  697.     MessageBox("This DIB has no palette to change",
  698.       GetApplication()->GetName(), MB_OK);
  699.     return;
  700.   }   
  701.  
  702.   TChooseColorDialog::TData choose;
  703.   choose.Flags = CC_RGBINIT;
  704.   PALETTEENTRY pe;
  705.   State->Palette->GetPaletteEntry((WORD)editColor, pe);
  706.   choose.Color = pe;
  707.   choose.CustColors = CustColors;
  708.  
  709.   if (TChooseColorDialog(this, choose).Execute() == IDOK) {
  710.     State->Dib->SetColor(editColor, choose.Color);
  711.     delete State->Palette;
  712.     State->Palette = new TPalette(*State->Dib);
  713.     Invalidate(false);
  714.     TWindow* canvas = GetParentO()->ChildWithId(ID_CANVAS);
  715.     if (canvas && canvas->GetHandle())
  716.       canvas->Invalidate(false);
  717.   }
  718. }
  719.  
  720. void
  721. TPaletteWindow::EvRButtonDown(UINT, TPoint& point)
  722. {
  723.   SelectColor(point, State->BgColor);
  724. }
  725.  
  726. void
  727. TPaletteWindow::EvRButtonDblClk(UINT modKeys, TPoint& point)
  728. {
  729.   EvLButtonDblClk(modKeys, point);
  730. }
  731.  
  732. LRESULT
  733. TPaletteWindow::EvSetRGB(TParam1, TParam2)
  734. {
  735.   Invalidate(false);
  736.   return 0;
  737. }
  738.  
  739. #if defined(USE_LINEBAR)
  740. // --------------- TLineBar ------------------------
  741.  
  742. TLineBar::TLineBar(TWindow* parent, TState* state)
  743.   : TWindow(parent),
  744.     State(state)
  745. {
  746.   Attr.Style |= WS_BORDER;
  747.   Attr.W = 32;
  748.   Attr.H = 32;
  749. }
  750.  
  751. void
  752. TLineBar::Notch(TDC& dc, int x, int w, int y, int dy)
  753. {
  754.   for (int l = 3; l >= 0; l--) {
  755.     dc.MoveTo(TPoint(x + w / 2 - l, y));
  756.     dc.LineTo(TPoint(x + w / 2 + l + 1, y));
  757.     y += dy;
  758.   }
  759. }
  760.  
  761. void
  762. TLineBar::Paint(TDC& dc, bool, TRect&)
  763. {
  764.   int x = 4;
  765.   dc.SelectStockObject(WHITE_BRUSH);
  766.   dc.PatBlt(TRect(0, 0, Attr.W, Attr.H));
  767.   dc.SelectStockObject(BLACK_BRUSH);
  768.   for (int i = 0; i < LineCount; i++) {
  769.     int w = LineWidth[i];
  770.     dc.PatBlt(TRect(x, 5, x + w, 25));
  771.     if (w == State->PenSize) {
  772.       Notch(dc, x, w, 0, 1);
  773.       Notch(dc, x, w, 29, -1);
  774.     }
  775.     x += w + 4;
  776.   }
  777. }
  778.  
  779. void
  780. TLineBar::EvLButtonDown(UINT, TPoint& point)
  781. {
  782.   int x = 2;
  783.   for (int i = 0; i < LineCount; i++) {
  784.     int w = LineWidth[i];
  785.     if (point.x >= x && point.x < x+w+4) {
  786.       TRACEX(PaintCmd,0,"Width = " << w);
  787.       State->PenSize = w;
  788.       Invalidate(false);
  789.       return;
  790.     }
  791.     x += w + 4;
  792.   }
  793. }
  794. #endif
  795.  
  796. // --------------- TCanvas ------------------------
  797.  
  798. TCanvas::TCanvas()
  799. :
  800.   TWindow(0, 0, 0),
  801.   Drawing(false)
  802. {
  803.   State.DrawTool = 0;
  804.   State.Dib = 0;
  805.   State.Bitmap = 0;
  806.   State.DC = 0;
  807.   State.Palette = 0;
  808.   State.PenSize = DefPenSize;
  809.   State.FgColor = 0;
  810.   State.BgColor = 1;
  811.   State.Name = State.Title = "";
  812.  
  813.   Scroller = 0;
  814.  
  815.   Tools[0] = new TPenTool("Pen");
  816.   Tools[1] = new TFillTool("Fill");
  817.   Tools[2] = new TRectTool("Rect", false);
  818.   Tools[3] = new TRectTool("FillRect", true);
  819.   Tools[4] = new TEllipseTool("Ellipse", false);
  820.   Tools[5] = new TEllipseTool("FillEllipse", true);
  821.   State.DrawTool = Tools[0];
  822.  
  823.   Attr.Id = ID_CANVAS;
  824.  
  825.   ToolsPal = LinesPal = 0;
  826.   
  827.   // Set transparent background to skip EvEraseBkgnd & erase during paint
  828.   //
  829.   SetBkgndColor(TColor::Transparent);
  830. }
  831.  
  832. TCanvas::~TCanvas()
  833. {
  834.   delete State.DC;
  835.   delete State.Palette;
  836.   delete State.Dib;
  837.   delete State.Bitmap;
  838.  
  839.   for (int i = 0; i < ToolCount; i++)
  840.     delete Tools[i];
  841. }
  842.  
  843. void
  844. TCanvas::SetupWindow()
  845. {
  846.   TWindow::SetupWindow();
  847.   NewDib(DefWidth, DefHeight, DefNColors);
  848.   DragAcceptFiles(true);
  849.  
  850.   // Construct the toolboxes if selected.
  851.   // Could Create() them here, or just wait for the menu selection to create
  852.   // them
  853.   //
  854. #if !defined(USE_TOOLBAR)
  855.   TToolBox* tb = new TToolBox(GetParentO());
  856.   tb->Insert(*new TButtonGadget(CM_TOOL+0, CM_TOOL+0, TButtonGadget::Exclusive,
  857.                                 true, TButtonGadget::Down));
  858.   tb->Insert(*new TButtonGadget(CM_TOOL+1, CM_TOOL+1, TButtonGadget::Exclusive, true));
  859.   tb->Insert(*new TButtonGadget(CM_TOOL+2, CM_TOOL+2, TButtonGadget::Exclusive, true));
  860.   tb->Insert(*new TButtonGadget(CM_TOOL+3, CM_TOOL+3, TButtonGadget::Exclusive, true));
  861.   tb->Insert(*new TButtonGadget(CM_TOOL+4, CM_TOOL+4, TButtonGadget::Exclusive, true));
  862.   tb->Insert(*new TButtonGadget(CM_TOOL+5, CM_TOOL+5, TButtonGadget::Exclusive, true));
  863.   ToolsPal = new TButtonPalette(this, "", tb);
  864.  
  865.   tb = new TToolBox(GetParentO());
  866.   tb->Insert(*new TButtonGadget(CM_LINE+1, CM_LINE+1, TButtonGadget::Exclusive,
  867.                                 true, TButtonGadget::Down));
  868.   tb->Insert(*new TButtonGadget(CM_LINE+3, CM_LINE+3, TButtonGadget::Exclusive, true));
  869.   tb->Insert(*new TButtonGadget(CM_LINE+5, CM_LINE+5, TButtonGadget::Exclusive, true));
  870.   tb->Insert(*new TButtonGadget(CM_LINE+7, CM_LINE+7, TButtonGadget::Exclusive, true));
  871.   tb->Insert(*new TButtonGadget(CM_LINE+9, CM_LINE+9, TButtonGadget::Exclusive, true));
  872.   tb->Insert(*new TButtonGadget(CM_LINE+11, CM_LINE+11, TButtonGadget::Exclusive, true));
  873.   LinesPal = new TButtonPalette(this, "", tb);
  874. #endif
  875.  
  876.   // A scroller on the client area would be nice...
  877.   //
  878.   //Scroller = new TScroller(this,1,1, State.Dib->Width(), State.Dib->Height());
  879.   SetFocus();
  880. }
  881.  
  882. bool
  883. TCanvas::CanClose()
  884. {
  885.   return AbandonOk();
  886. }
  887.  
  888. bool
  889. TCanvas::AbandonOk()
  890. {
  891.   if (!State.Modified)
  892.     return true;
  893.   const char msgFrmt[] = "%s\nThe image has changed.\n\n"
  894.                          "Do you want to save current changes?";
  895.   char msg[sizeof(msgFrmt)+100];
  896.   sprintf(msg, msgFrmt, State.Name.c_str());
  897.   int resp = MessageBox(msg, GetApplication()->GetName(),
  898.                         MB_ICONEXCLAMATION|MB_YESNOCANCEL);
  899.   if (resp == IDYES)
  900.     CmFileSave();
  901.  
  902.   return resp != IDCANCEL;
  903. }
  904.  
  905. //
  906. // Setup state info given a new dib. Assumes ownership of the dib.
  907. //
  908. void
  909. TCanvas::SetupDib(TDib* dib, const char* name, const char* title)
  910. {
  911.   TPalette* newPalette;
  912.  
  913.   // Make a palette for the DIB.
  914.   //
  915.   try {
  916.     newPalette = new TPalette(*dib);
  917.   }
  918.   catch (TGdiObject::TXGdi&) {
  919.  
  920.     // Probably DIB is true color and therefore lacks a color table.
  921.     // We still need a palette object.  If the current display device
  922.     // supports palettes, then select a halftone palette because that
  923.     // will have a good range of colors to choose from.  If the
  924.     // current display does not support palettes (because it's a high-
  925.     // color display), just use the stock palette.
  926.     //
  927.     TScreenDC display;
  928.     if (display.GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
  929.       newPalette = new THalftonePalette();
  930.     else
  931.       newPalette = new TPalette((HPALETTE)::GetStockObject(DEFAULT_PALETTE));
  932.  
  933.  
  934.     // (There are better ways to set up a palette for rendering a
  935.     // high-color image with a limited color set.  It's preferable
  936.     // to scan the DIB's colors and make intelligent choices about
  937.     // which to use--that's a standard problem, and you can find 
  938.     // articles describing ways to do it.)
  939.   }
  940.  
  941.   TMemoryDC* newDC = new TMemoryDC;
  942.   TBitmap*   newBM = new TBitmap(TScreenDC(), *dib, 0);
  943.  
  944.   SetCursor(0, IDC_WAIT);
  945.   newDC->SelectObject(*newPalette);
  946.   newDC->RealizePalette();
  947.   newDC->SelectObject(*newBM);
  948.   newDC->SetDIBits(*newBM, *dib);
  949.   SetCursor(0, IDC_ARROW);
  950.  
  951.   delete State.DC;
  952.   delete State.Palette;
  953.   delete State.Dib;
  954.   delete State.Bitmap;
  955.  
  956.   State.DC      = newDC;
  957.   State.Palette = newPalette;
  958.   State.Dib     = dib;
  959.   State.Bitmap  = newBM;
  960.   State.Name    = name;
  961.   State.Title   = title;
  962.   State.Modified = false;
  963.  
  964.   UpdateCaption();
  965.   AdjustScroller();
  966.   TWindow* palette = GetParentO()->ChildWithId(ID_PALETTE);
  967.   if (palette && palette->GetHandle())
  968.     palette->Invalidate(false);
  969.   Invalidate(false);
  970. }
  971.  
  972. //
  973. // Create a new dib & setup state info
  974. //
  975. void
  976. TCanvas::NewDib(int width, int height, uint32 nColors)
  977. {
  978.   // Construct the DIB, catching any exceptions that might occur and
  979.   // displaying a warning
  980.   //
  981.   TDib* dib;
  982.   try {
  983.     dib = new TDib(width, height, nColors);
  984.   }
  985.   catch (TGdiObject::TXGdi& x) {
  986.     MessageBox("Cannot create DIB", GetApplication()->GetName(), MB_OK);
  987.     return;
  988.   }
  989.  
  990.   // Convert number of colors supported to number of colors
  991.   // needed in color table.  For high-color images, the color
  992.   // table size is 0.
  993.   //
  994.   int nColorsInTable = (int)NColors(NBits(nColors));
  995.  
  996.   // If a palette is needed, set up a reasonable default.
  997.   //
  998.   int nDefPalette = sizeof(DefPalette) / sizeof(DefPalette[0]);
  999.   if (nColorsInTable)
  1000.     for (int i = 0; i < min(nColorsInTable, nDefPalette); i++)
  1001.       dib->SetColor(i, DefPalette[i]);
  1002.  
  1003.   SetupDib(dib, "", "(Untitled)");
  1004.  
  1005.   TBrush brush(TColor(State.BgColor));
  1006.   State.DC->SelectObject(*State.Palette);
  1007.   State.DC->RealizePalette();
  1008.   State.DC->SelectObject(brush);
  1009.   State.DC->PatBlt(TRect(TPoint(0,0), State.Dib->Size()));
  1010.   State.DC->RestoreObjects();
  1011. }
  1012.  
  1013. //
  1014. // Open a dib & setup state info given a dib filename & title
  1015. //
  1016. void
  1017. TCanvas::OpenDib(const char* fileName, const char* fileTitle)
  1018. {
  1019.   TDib* dib;
  1020.   try {
  1021.     dib = new TDib(fileName);
  1022.   }
  1023.   catch (TGdiObject::TXGdi& x) {
  1024.     MessageBox("Invalid Bitmap File", GetApplication()->GetName(), MB_OK);
  1025.     return;
  1026.   }
  1027.  
  1028.   SetupDib(dib, fileName, fileTitle);
  1029. }
  1030.  
  1031. bool
  1032. TCanvas::SaveDib(const char* fileName)
  1033. {
  1034.   if (State.Bitmap) {
  1035.     delete State.Dib;
  1036.     State.Dib = new TDib(*State.Bitmap,
  1037.       // add the palette if the bitmap needs it
  1038.       State.Bitmap->BitsPixel() <= 8 ? State.Palette : 0);
  1039.   }
  1040.   if (State.Dib->WriteFile(fileName))
  1041.     return true;
  1042.   MessageBox("Disk error saving bitmap!", GetApplication()->GetName(), MB_OK);
  1043.   return false;
  1044. }
  1045.  
  1046. void
  1047. TCanvas::UpdateCaption()
  1048. {
  1049.   char captionBuffer[70];
  1050.   if (State.Dib)
  1051.     sprintf(captionBuffer, "%s - %s [%dx%dx%lu]", GetApplication()->GetName(),
  1052.              (LPCSTR)State.Title.c_str(),
  1053.              State.Dib->Width(), State.Dib->Height(), 
  1054.              ColorCapacity(State.Dib->BitsPixel()));
  1055.   else
  1056.     sprintf(captionBuffer, "%s - (Bad Dib!)", GetApplication()->GetName());
  1057.   GetParentO()->SetCaption(captionBuffer);
  1058. }
  1059.  
  1060. void
  1061. TCanvas::AdjustScroller()
  1062. {
  1063.   if (!Scroller)
  1064.     return;
  1065.  
  1066.   TRect  clientRect = GetClientRect();
  1067.  
  1068.   // only show scrollbars when image is larger than
  1069.   // the client area and we are not stretching to fit.
  1070.   //
  1071.   TPoint range(Max(State.Dib->Width()-clientRect.Width(), 0),
  1072.                Max(State.Dib->Height()-clientRect.Height(), 0));
  1073.   Scroller->SetRange(range.x, range.y);
  1074.   Scroller->ScrollTo(0, 0);
  1075.   if (!GetUpdateRect(clientRect, false))
  1076.     Invalidate(false);
  1077. }
  1078.  
  1079. void
  1080. TCanvas::EvSize(UINT SizeType, TSize& Size)
  1081. {
  1082.   TWindow::EvSize(SizeType, Size);
  1083.   if (SizeType != SIZEICONIC)
  1084.     AdjustScroller();
  1085. }
  1086.  
  1087. void
  1088. TCanvas::Paint(TDC& dc, bool, TRect&)
  1089. {
  1090.   TRect drect(TPoint(0,0), State.Dib->Size());
  1091.   TRect crect = GetClientRect();
  1092.   if (Scroller)
  1093.     crect += TPoint((int)Scroller->XPos, (int)Scroller->YPos);
  1094.  
  1095.   // optimize this painting!
  1096.   //TRect prect(rect);
  1097.   //drect &= prect;
  1098.   dc.SelectObject(*State.Palette);
  1099.   dc.RealizePalette();
  1100.  
  1101.   // Blit the DDB or DIB from the working DC to the screen
  1102.   //
  1103.   if (State.Bitmap)
  1104.     dc.BitBlt(drect, *State.DC, TPoint(0,0));
  1105.   else
  1106.     dc.SetDIBitsToDevice(drect, TPoint(0,0), *State.Dib);
  1107.  
  1108.   // Paint around the canvas
  1109.   //
  1110.   TBrush bkBrush(TColor::SysAppWorkspace);  // or SysWindow
  1111.   dc.SelectObject(bkBrush);
  1112.   dc.PatBlt(TRect(drect.right, 0, crect.right, crect.bottom));
  1113.   dc.PatBlt(TRect(0, drect.bottom, crect.right, crect.bottom));
  1114.  
  1115.   dc.RestoreObjects();
  1116. }
  1117.  
  1118. void
  1119. TCanvas::EvLButtonDown(UINT modKeys, TPoint& point)
  1120. {
  1121.   TWindow::EvLButtonDown(modKeys, point);
  1122.   if (!Drawing) {
  1123.     Drawing = true;
  1124.     State.DrawTool->MouseDown(*this, point, &State);
  1125.   }
  1126. }
  1127.  
  1128. void
  1129. TCanvas::EvMouseMove(UINT, TPoint& point)
  1130. {
  1131.   if (Drawing)
  1132.     State.DrawTool->MouseMove(point);
  1133. }
  1134.  
  1135. void
  1136. TCanvas::EvLButtonUp(UINT, TPoint& point)
  1137. {
  1138.   if (Drawing) {
  1139.     State.DrawTool->MouseMove(point);
  1140.     State.DrawTool->MouseUp();
  1141.     Drawing = false;
  1142.   }
  1143. }
  1144.  
  1145. void
  1146. TCanvas::EvDropFiles(TDropInfo dropInfo)
  1147. {
  1148.   int totalNumberOfFiles = dropInfo.DragQueryFileCount();
  1149.   if (totalNumberOfFiles == 1 && AbandonOk()) {
  1150.     char filePath[MAXPATH+1];
  1151.     char fileTitle[MAXFILE];
  1152.     dropInfo.DragQueryFile(0, filePath, MAXPATH + 1);
  1153.     fnsplit(filePath, 0, 0, fileTitle, 0);
  1154.     OpenDib(filePath, fileTitle);
  1155.   }
  1156.   dropInfo.DragFinish();
  1157. }
  1158.  
  1159. void
  1160. TCanvas::CmTool(TParam1 toolCmd)
  1161. {
  1162.   int i = toolCmd - CM_TOOL;
  1163.   TRACEX(PaintCmd,0, "Tool = " << Tools[i]->GetName());
  1164.   State.DrawTool = Tools[i];
  1165.  
  1166.   SetCursor(GetModule(), toolCmd);
  1167. }
  1168.  
  1169. void
  1170. TCanvas::CmLine(TParam1 lineCmd)
  1171. {
  1172.   State.PenSize = lineCmd - CM_LINE;
  1173. }
  1174.  
  1175. void
  1176. TCanvas::CmFileNew()
  1177. {
  1178.   TRACEX(PaintCmd,0,"CmFileNew()");
  1179.   if (!AbandonOk())
  1180.     return;
  1181.  
  1182.   static int width = DefWidth;
  1183.   static int height = DefHeight;
  1184.   static uint32 ncolors = DefNColors;
  1185.   if (TDibAttrDialog(this, width, height, ncolors).Execute() == IDOK)
  1186.     NewDib(width, height, ncolors);
  1187. }
  1188.  
  1189. void
  1190. TCanvas::CmFileOpen()
  1191. {
  1192.   TRACEX(PaintCmd,0,"CmFileOpen()");
  1193.   if (!AbandonOk())
  1194.     return;
  1195.  
  1196.   TOpenSaveDialog::TData data (
  1197.     OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_NOREADONLYRETURN,
  1198.     "Bitmap Files (*.BMP)|*.bmp|",
  1199.     0,
  1200.     "",
  1201.     "BMP"
  1202.   );
  1203.   if (TFileOpenDialog(this, data).Execute() == IDOK) {
  1204.     char fileTitle[MAXPATH];
  1205.     TOpenSaveDialog::GetFileTitle(data.FileName, fileTitle, MAXPATH);
  1206.     OpenDib(data.FileName, fileTitle);
  1207.   }
  1208. }
  1209.  
  1210. void
  1211. TCanvas::CmFileSave()
  1212. {
  1213.   TRACEX(PaintCmd,0,"CmFileSave()");
  1214.   if (State.Modified) {
  1215.     if (!State.Name.length()) {
  1216.       CmFileSaveAs();
  1217.       return;
  1218.     }
  1219.  
  1220.     if (SaveDib(State.Name.c_str()))
  1221.       State.Modified = false;
  1222.   }
  1223. }
  1224.  
  1225. void
  1226. TCanvas::CmFileSaveAs()
  1227. {
  1228.   TRACEX(PaintCmd,0,"CmFileSaveAs()");
  1229.   TOpenSaveDialog::TData data (
  1230.     OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
  1231.     "Bitmap Files (*.BMP)|*.bmp|",
  1232.     0,
  1233.     "",
  1234.     "BMP"
  1235.   );
  1236.   if (TFileSaveDialog(this, data).Execute() == IDOK) {
  1237.     if (SaveDib(data.FileName)) {
  1238.       State.Name = data.FileName;
  1239.       State.Modified = false;
  1240.       char fileTitle[MAXPATH];
  1241.       TOpenSaveDialog::GetFileTitle(data.FileName, fileTitle, MAXPATH);
  1242.       State.Title = fileTitle;
  1243.       UpdateCaption();
  1244.     }
  1245.   }
  1246. }
  1247.  
  1248. void
  1249. TCanvas::CmFilePrint()
  1250. {
  1251.   TRACEX(PaintCmd, 0, "CmFilePrint()");
  1252.   PrintData.Flags &= ~PD_PRINTSETUP;
  1253.   if (TPrintDialog(this, PrintData).Execute() == IDOK) {
  1254.     MessageBox("No File|Print yet...", GetApplication()->GetName(), MB_OK);
  1255.   }
  1256. }
  1257.  
  1258. void
  1259. TCanvas::CmFilePrintSetup()
  1260. {
  1261.   TRACEX(PaintCmd, 0, "CmFilePrintSetup()");
  1262.   PrintData.Flags |= PD_PRINTSETUP;
  1263.   TPrintDialog(this, PrintData, 0).Execute();
  1264. }
  1265.  
  1266. void
  1267. TCanvas::CmViewTools()
  1268. {
  1269.   if (ToolsPal)
  1270.     if (ToolsPal->GetHandle())
  1271.       ToolsPal->Destroy();
  1272.     else
  1273.       ToolsPal->Create();
  1274. }
  1275.  
  1276. void
  1277. TCanvas::CeViewTools(TCommandEnabler& ce)
  1278. {
  1279.   if (!ToolsPal)
  1280.     ce.Enable(false);
  1281.   else
  1282.     ce.SetCheck(ToolsPal->GetHandle() ?
  1283.                 TCommandEnabler::Checked : TCommandEnabler::Unchecked);
  1284. }
  1285.  
  1286. void
  1287. TCanvas::CmViewLines()
  1288. {
  1289.   if (LinesPal)
  1290.     if (LinesPal->GetHandle())
  1291.       LinesPal->Destroy();
  1292.     else
  1293.       LinesPal->Create();
  1294. }
  1295.  
  1296. void
  1297. TCanvas::CeViewLines(TCommandEnabler& ce)
  1298. {
  1299.   if (!LinesPal)
  1300.     ce.Enable(false);
  1301.   else
  1302.     ce.SetCheck(LinesPal->GetHandle() ?
  1303.                 TCommandEnabler::Checked : TCommandEnabler::Unchecked);
  1304. }
  1305.  
  1306.  
  1307. //----------------------------------------------------------------------------
  1308.  
  1309. class TPaintApp : public TApplication {
  1310.   public:
  1311.     TPaintApp() : TApplication("OWL Paint") {}
  1312.     void InitMainWindow();
  1313. };
  1314.  
  1315. void TPaintApp::InitMainWindow()
  1316. {
  1317.   TCanvas& client = *new TCanvas;
  1318.   TDecoratedFrame* frame = new TDecoratedFrame(0, Name, &client);
  1319.  
  1320. #if defined(USE_TOOLBAR)
  1321.   TControlBar* cb = new TControlBar(frame);
  1322.   cb->Insert(*new TButtonGadget(CM_TOOL+0, CM_TOOL+0, TButtonGadget::Exclusive,
  1323.                                 false, TButtonGadget::Down));
  1324.   cb->Insert(*new TButtonGadget(CM_TOOL+1, CM_TOOL+1, TButtonGadget::Exclusive));
  1325.   cb->Insert(*new TButtonGadget(CM_TOOL+2, CM_TOOL+2, TButtonGadget::Exclusive));
  1326.   cb->Insert(*new TButtonGadget(CM_TOOL+3, CM_TOOL+3, TButtonGadget::Exclusive));
  1327.   cb->Insert(*new TButtonGadget(CM_TOOL+4, CM_TOOL+4, TButtonGadget::Exclusive));
  1328.   cb->Insert(*new TButtonGadget(CM_TOOL+5, CM_TOOL+5, TButtonGadget::Exclusive));
  1329. #if !defined(USE_LINEBAR)
  1330.   cb->Insert(*new TSeparatorGadget);
  1331.   cb->Insert(*new TButtonGadget(CM_LINE+1, CM_LINE+1, TButtonGadget::Exclusive));
  1332.   cb->Insert(*new TButtonGadget(CM_LINE+3, CM_LINE+3, TButtonGadget::Exclusive,
  1333.                                 false, TButtonGadget::Down));
  1334.   cb->Insert(*new TButtonGadget(CM_LINE+5, CM_LINE+5, TButtonGadget::Exclusive));
  1335.   cb->Insert(*new TButtonGadget(CM_LINE+7, CM_LINE+7, TButtonGadget::Exclusive));
  1336.   cb->Insert(*new TButtonGadget(CM_LINE+9, CM_LINE+9, TButtonGadget::Exclusive));
  1337.   cb->Insert(*new TButtonGadget(CM_LINE+11, CM_LINE+11, TButtonGadget::Exclusive));
  1338. #endif
  1339.   frame->Insert(*cb, TDecoratedFrame::Top);
  1340. #endif
  1341.  
  1342.   frame->Insert(*new TPaletteWindow(frame, &client.State), TDecoratedFrame::Bottom);
  1343. #if defined(USE_LINEBAR)
  1344.   frame->Insert(*new TLineBar(frame, &client.State), TDecoratedFrame::Bottom);
  1345. #endif
  1346.  
  1347.   frame->AssignMenu("PaintMenu");
  1348.   frame->Attr.AccelTable = "PaintAccels";
  1349.   frame->SetIcon(this, "PaintIcon");
  1350.  
  1351.   SetMainWindow(frame);
  1352. }
  1353.  
  1354. int
  1355. OwlMain(int /*argc*/, char* /*argv*/ [])
  1356. {
  1357.   TScreenDC screenDC;
  1358.  
  1359.   DefNColors = ColorCapacity(screenDC.GetDeviceCaps(BITSPIXEL)*screenDC.GetDeviceCaps(PLANES));
  1360.   return TPaintApp().Run();
  1361. }
  1362.